import mongoose from 'mongoose';
import Group, { IGroup, IGroupDocument } from '../models/group';

/**
 * 小组数据访问对象
 * 提供小组相关的数据库操作方法
 */
export class GroupDAO {
  /**
   * 创建新小组
   * @param groupData 小组数据
   * @returns 创建的小组文档
   */
  async create(groupData: Partial<IGroup>): Promise<IGroupDocument> {
    try {
      const group = new Group(groupData);
      return await group.save();
    } catch (error: any) {
      if (error.code === 11000) {
        // 处理唯一性约束错误
        const field = Object.keys(error.keyPattern)[0];
        throw new Error(`${field} already exists`);
      }
      throw error;
    }
  }

  /**
   * 根据ID查找小组
   * @param id 小组ID
   * @returns 小组文档或null
   */
  async findById(id: mongoose.Types.ObjectId | string): Promise<IGroupDocument | null> {
    try {
      if (!mongoose.Types.ObjectId.isValid(id)) {
        throw new Error('Invalid group ID format');
      }
      return await Group.findById(id).exec();
    } catch (error) {
      throw error;
    }
  }

  /**
   * 根据部门ID查找小组
   * @param departmentId 部门ID
   * @returns 小组文档数组
   */
  async findByDepartment(departmentId: mongoose.Types.ObjectId | string): Promise<IGroupDocument[]> {
    try {
      if (!mongoose.Types.ObjectId.isValid(departmentId)) {
        throw new Error('Invalid department ID format');
      }
      return await Group.findByDepartment(departmentId as mongoose.Types.ObjectId);
    } catch (error) {
      throw error;
    }
  }

  /**
   * 更新小组信息
   * @param id 小组ID
   * @param updateData 更新数据
   * @returns 更新后的小组文档或null
   */
  async update(
    id: mongoose.Types.ObjectId | string,
    updateData: Partial<IGroup>
  ): Promise<IGroupDocument | null> {
    try {
      if (!mongoose.Types.ObjectId.isValid(id)) {
        throw new Error('Invalid group ID format');
      }

      // 移除不应该被更新的字段
      const { _id, createdAt, ...safeUpdateData } = updateData as any;
      
      // 设置更新时间
      safeUpdateData.updatedAt = new Date();

      const updatedGroup = await Group.findByIdAndUpdate(
        id,
        safeUpdateData,
        { 
          new: true, 
          runValidators: true,
          lean: false
        }
      ).exec();

      return updatedGroup;
    } catch (error: any) {
      if (error.code === 11000) {
        // 处理唯一性约束错误
        const field = Object.keys(error.keyPattern)[0];
        throw new Error(`${field} already exists`);
      }
      throw error;
    }
  }

  /**
   * 删除小组
   * @param id 小组ID
   * @returns 是否删除成功
   */
  async delete(id: mongoose.Types.ObjectId | string): Promise<boolean> {
    try {
      if (!mongoose.Types.ObjectId.isValid(id)) {
        throw new Error('Invalid group ID format');
      }

      const result = await Group.findByIdAndDelete(id).exec();
      return result !== null;
    } catch (error) {
      throw error;
    }
  }

  /**
   * 根据小组名称查找小组
   * @param name 小组名称
   * @returns 小组文档或null
   */
  async findByName(name: string): Promise<IGroupDocument | null> {
    try {
      if (!name || name.trim().length === 0) {
        throw new Error('Group name cannot be empty');
      }
      return await Group.findByName(name);
    } catch (error) {
      throw error;
    }
  }

  /**
   * 根据组长ID查找小组
   * @param leaderId 组长ID
   * @returns 小组文档或null
   */
  async findByLeader(leaderId: mongoose.Types.ObjectId | string): Promise<IGroupDocument | null> {
    try {
      if (!mongoose.Types.ObjectId.isValid(leaderId)) {
        throw new Error('Invalid leader ID format');
      }
      return await Group.findByLeader(leaderId as mongoose.Types.ObjectId);
    } catch (error) {
      throw error;
    }
  }

  /**
   * 根据状态查找小组列表
   * @param status 状态值
   * @returns 小组文档数组
   */
  async findByStatus(status: number): Promise<IGroupDocument[]> {
    try {
      if (status !== 0 && status !== 1) {
        throw new Error('Invalid status value. Must be 0 or 1');
      }
      return await Group.findByStatus(status);
    } catch (error) {
      throw error;
    }
  }

  /**
   * 查找所有小组（支持条件查询和分页）
   * @param criteria 查询条件
   * @param options 查询选项
   * @returns 小组列表和分页信息
   */
  async findAll(
    criteria: {
      name?: string;
      departmentId?: mongoose.Types.ObjectId | string;
      leaderId?: mongoose.Types.ObjectId | string;
      status?: number;
    } = {},
    options: {
      page?: number;
      limit?: number;
      sort?: string;
      select?: string;
    } = {}
  ): Promise<{ groups: IGroupDocument[]; total: number; page: number; totalPages: number }> {
    try {
      const {
        page = 1,
        limit = 10,
        sort = '-createdAt',
        select = ''
      } = options;

      // 构建查询条件
      const query: any = {};
      
      if (criteria.name) {
        query.name = { $regex: criteria.name, $options: 'i' };
      }
      
      if (criteria.departmentId) {
        if (!mongoose.Types.ObjectId.isValid(criteria.departmentId)) {
          throw new Error('Invalid department ID format');
        }
        query.departmentId = criteria.departmentId;
      }
      
      if (criteria.leaderId) {
        if (!mongoose.Types.ObjectId.isValid(criteria.leaderId)) {
          throw new Error('Invalid leader ID format');
        }
        query.leaderId = criteria.leaderId;
      }
      
      if (criteria.status !== undefined) {
        if (criteria.status !== 0 && criteria.status !== 1) {
          throw new Error('Invalid status value. Must be 0 or 1');
        }
        query.status = criteria.status;
      }

      // 计算跳过的文档数量
      const skip = (page - 1) * limit;

      // 执行查询
      const [groups, total] = await Promise.all([
        Group.find(query)
          .select(select)
          .sort(sort)
          .skip(skip)
          .limit(limit)
          .exec(),
        Group.countDocuments(query).exec()
      ]);

      // 计算总页数
      const totalPages = Math.ceil(total / limit);

      return {
        groups,
        total,
        page,
        totalPages
      };
    } catch (error) {
      throw error;
    }
  }

  /**
   * 批量创建小组
   * @param groupsData 小组数据数组
   * @returns 创建的小组文档数组
   */
  async batchCreate(groupsData: Partial<IGroup>[]): Promise<IGroupDocument[]> {
    try {
      if (!Array.isArray(groupsData) || groupsData.length === 0) {
        throw new Error('Groups data must be a non-empty array');
      }

      // 验证每个小组数据
      for (const groupData of groupsData) {
        if (!groupData.name || !groupData.departmentId) {
          throw new Error('Each group must have name and departmentId');
        }
      }

      return await Group.insertMany(groupsData, { ordered: false });
    } catch (error: any) {
      if (error.code === 11000) {
        throw new Error('Duplicate group name in department');
      }
      throw error;
    }
  }

  /**
   * 更新小组状态
   * @param id 小组ID
   * @param status 新状态
   * @returns 更新后的小组文档或null
   */
  async updateStatus(
    id: mongoose.Types.ObjectId | string,
    status: number
  ): Promise<IGroupDocument | null> {
    try {
      if (!mongoose.Types.ObjectId.isValid(id)) {
        throw new Error('Invalid group ID format');
      }

      if (status !== 0 && status !== 1) {
        throw new Error('Invalid status value. Must be 0 or 1');
      }

      return await Group.findByIdAndUpdate(
        id,
        { status, updatedAt: new Date() },
        { new: true, runValidators: true }
      ).exec();
    } catch (error) {
      throw error;
    }
  }
}

export default GroupDAO;